home *** CD-ROM | disk | FTP | other *** search
/ PC User 2003 January / Disc 1 / PCU0103CD1.iso / entertn / demos / files / aomtrial.exe / AOM / AI / SCN33P6.XS < prev    next >
Encoding:
Text File  |  2002-09-17  |  20.0 KB  |  692 lines

  1. //==============================================================================
  2. // Scn33p6: AI Scenario Script for scenario 33 player 6
  3. //==============================================================================
  4. /*
  5.    AI owner:  Mike Kidd
  6.    Scenario owner: Jeff Brown
  7.  
  8.    Overview:
  9.    
  10.    Player 6 is Greek, and appears to the HP to be the same as player 2 (Norse).
  11.    Player 6's role is to steadily harrass the player continuously, until the final
  12.    segment. Then, while player 2 keeps attacking, player 6 pulls all units back
  13.    to protect gargarensis.
  14.      
  15. */
  16. //==============================================================================
  17.  
  18.  
  19. include "scn lib.xs";
  20.  
  21.  
  22. // *****************************************************************************
  23. //
  24. // Globals
  25. //
  26. // *****************************************************************************
  27.  
  28.  
  29. // Cinematic blocks
  30.  
  31. const string cbDefendPoint = "2884";
  32. const string cbAttackGather = "2887";
  33. const string cbTownCenter = "2889";
  34. const string cbGarg = "2898";       // Gargarensis's hideout
  35. const string cbRouteA1 = "2891";      // East side
  36. const string cbRouteA2 = "2892";
  37. const string cbRouteA3 = "2893";
  38. const string cbRouteB1 = "2891";      // Center
  39. const string cbRouteB2 = "2892";
  40. const string cbRouteB3 = "2894";
  41. const string cbRouteC1 = "2891";      // West
  42. const string cbRouteC2 = "2895";
  43. const string cbRouteC3 = "2896";
  44.  
  45.  
  46. // Attack routes and queries
  47. int   routeA = -1;
  48. int   routeB = -1;
  49. int   routeC = -1;
  50.  
  51.  
  52. // Army control
  53. int   lastAttackPlan = -1;       // Used to find "my army" for god power position info
  54. int   defendPlan = -1;
  55. int   explorePlan = -1;
  56.  
  57. // The following are set in main() based on difficulty level.
  58. int      nextAttackTime = 180000;   // Will be adjusted for the wakeup time
  59. int      attackInterval = 240000;   // Attack every 4:00 
  60. float    attackSize = 3.0;
  61. float    attackMultiplier = 1.2;
  62. int      maxAttackSize = 8;
  63.  
  64. //    Upgrade timer control
  65. int      startTime = -1;
  66. int      endTime = -1;
  67.  
  68.  
  69. int   maintainQty1 = -1;         // Quantity to maintain
  70. int   maintainUnit1 = -1;        // Unit type
  71. int   maintainDelay1 = -1;       // Interval between training units
  72. vector   maintainGather1 = cInvalidVector;
  73. int   maintainID1 = -1;          // Maintain plan for primary military unit
  74.  
  75. int   maintainQty2 = -1;         // Quantity to maintain
  76. int   maintainUnit2 = -1;        // Unit type
  77. int   maintainDelay2 = -1;       // Interval between training units
  78. vector   maintainGather2 = cInvalidVector;
  79. int   maintainID2 = -1;          // Maintain plan for secondary military unit
  80.  
  81. int   maintainQty3 = -1;         // Quantity to maintain
  82. int   maintainUnit3 = -1;        // Unit type
  83. int   maintainDelay3 = -1;       // Interval between training units
  84. vector   maintainGather3 = cInvalidVector;
  85. int   maintainID3 = -1;          // Maintain plan for tertiary military unit
  86.  
  87. int   maintainQty4 = -1;         // Quantity to maintain
  88. int   maintainUnit4 = -1;        // Unit type
  89. int   maintainDelay4 = -1;       // Interval between training units
  90. vector   maintainGather4 = cInvalidVector;
  91. int   maintainID4 = -1;          // Maintain plan for quatenary military unit
  92.  
  93. int   maintainQtyScout = 1;
  94. int   maintainUnitScout = cUnitTypeScout;
  95. int   maintainDelayScout = 1;
  96. vector   maintainGatherScout = cInvalidVector;
  97. int   maintainIDScout = -1;      // Scout unit
  98.  
  99.  
  100.  
  101.  
  102.  
  103. // Misc.
  104. int   age2Time = -1;       // Will be adjusted in main() for difficulty
  105. int   age3Time = -1;        
  106. int   age4Time = -1;       
  107.  
  108. int   difficulty = -1;     // Global to store difficulty, set early in main.
  109.  
  110.  
  111.  
  112. // *****************************************************************************
  113. //
  114. //                                FUNCTIONS
  115. //
  116. // *****************************************************************************
  117.  
  118.  
  119. // Called by trigger when the cinematics are done
  120.  
  121. void wakeup(int parm=-1)
  122. {
  123.    static bool alreadyRun = false;
  124.    aiEcho("Wakeup running at "+timeString()+".");
  125.    if (alreadyRun == true)
  126.       return;
  127.    alreadyRun = true;
  128.  
  129.    startTime = xsGetTime();
  130.    endTime = startTime + 20*60*1000;   // When does the army arrive?
  131.  
  132.    if (age2Time > 0)
  133.       age2Time = age2Time + startTime; // Adjust for delay in wakeup.
  134.    if (age3Time > 0)
  135.       age3Time = age3Time + startTime;     
  136.    if (age4Time > 0)
  137.       age4Time = age4Time + startTime;
  138.    if (nextAttackTime  > 0)
  139.       nextAttackTime = nextAttackTime + startTime;
  140.  
  141.  
  142.  
  143.    // Init low-priority defend plan to manage all extra mil units
  144.    defendPlan =aiPlanCreate("Defend Plan", cPlanDefend);
  145.    if (defendPlan >= 0)
  146.    {
  147.       aiPlanAddUnitType(defendPlan, cUnitTypeMilitary, 0, 200, 200);    // All unassigned mil units
  148.       aiPlanSetDesiredPriority(defendPlan, 10);                       // Way low, below scouting and attack
  149.       aiPlanSetVariableVector(defendPlan, cDefendPlanDefendPoint, 0, kbGetBlockPosition(cbDefendPoint));
  150.       aiPlanSetVariableFloat(defendPlan, cDefendPlanEngageRange, 0, 20);
  151.       aiPlanSetVariableBool(defendPlan, cDefendPlanPatrol, 0, false);
  152.       aiPlanSetVariableFloat(defendPlan, cDefendPlanGatherDistance, 0, 20.0);
  153.       aiPlanSetVariableInt(defendPlan, cDefendPlanRefreshFrequency, 0, 5);
  154.       aiPlanSetNumberVariableValues(defendPlan, cDefendPlanAttackTypeID, 2, true);
  155.       aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 0, cUnitTypeUnit);
  156.       aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 1, cUnitTypeBuilding);
  157.  
  158.       aiPlanSetInitialPosition(defendPlan, kbGetBlockPosition(cbAttackGather));
  159.       aiPlanSetActive(defendPlan); 
  160.       aiEcho("Creating defend plan");
  161.    }
  162.  
  163.    aiUnitCreateCheat( cMyID, cUnitTypeHydra, kbGetBlockPosition(cbDefendPoint), "Hydra", 2 + 2*aiGetWorldDifficulty()); 
  164.  
  165.    xsEnableRule("scout");
  166.    xsEnableRule("attackGenerator");
  167.    xsEnableRule("upgradeGenerator");
  168.    xsEnableRule("usePestilence");
  169. }
  170.  
  171.  
  172.  
  173. void defend(int ignore = -1)     // An aiFunc signal to fall back and defend gargarensis
  174. {
  175.    aiEcho("Defend firing at "+timeString());
  176.    aiPlanDestroy(lastAttackPlan);   // Call off attacks
  177.    xsDisableRule("attackGenerator");   // No more attacks
  178.    aiPlanSetVariableVector(defendPlan, cDefendPlanDefendPoint, 0, kbGetBlockPosition(cbGarg));
  179.    aiPlanSetVariableFloat(defendPlan, cDefendPlanEngageRange, 0, 50);
  180.    aiPlanSetUnitStance(defendPlan, cUnitStanceDefensive);
  181. }
  182.  
  183.  
  184.  
  185. void attack(int size=0)
  186. {
  187.  
  188.    int   attackID=aiPlanCreate("Attack at "+timeString(true)+" ", cPlanAttack);
  189.    if (attackID < 0) 
  190.       return;
  191.  
  192.    if (aiPlanSetVariableInt(attackID, cAttackPlanPlayerID, 0, 1) == false)
  193.       return;
  194.  
  195.    if (aiPlanSetNumberVariableValues(attackID, cAttackPlanTargetTypeID, 3, true) == false)
  196.       return;
  197.  
  198.    aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
  199.    aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding);
  200.    aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 2, cUnitTypeAbstractWall);
  201.  
  202.  
  203.    
  204.    switch(aiRandInt(3))
  205.    {
  206.    case 0:
  207.       {
  208.          aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeA);
  209.          break;
  210.       }
  211.    case 1:
  212.       {
  213.          aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeB);
  214.          break;
  215.       }
  216.    case 2:
  217.       {
  218.          aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeC);
  219.          break;
  220.       }
  221.    }
  222.  
  223.  
  224.    aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint, 0, kbGetBlockPosition(cbAttackGather));
  225.    aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 20.0);
  226.  
  227.  
  228.    aiPlanAddUnitType(attackID, maintainUnit1, 0, (size+8)/10, (size+8)/10);  // cyclops
  229.    aiPlanAddUnitType(attackID, maintainUnit2, 0, (4*size+2)/10, (4*size+2)/10);  // hippikon
  230.    aiPlanAddUnitType(attackID, maintainUnit3, 0, (5*size+5)/10, (5*size+5)/10);  // toxotes
  231.    aiPlanAddUnitType(attackID, cUnitTypeShadeofHades, 0, 20, 20);
  232.  
  233.    if ( (endTime - xsGetTime()) < 15*60*1000)
  234.    {
  235.       aiEcho("  adding hydra(s) to attack plan.");
  236.       aiPlanAddUnitType(attackID, maintainUnit4, 0, size/7, size/7);      // hydra
  237.    }
  238.  
  239.    aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbAttackGather));
  240.    aiPlanSetRequiresAllNeedUnits(attackID, false);
  241.    aiPlanSetDesiredPriority(attackID, 50);   // Less than scouting, more than defense
  242.    aiPlanSetActive(attackID);
  243.    aiEcho("Activating attack plan "+attackID+" with appx "+size+" units.");
  244.    lastAttackPlan = attackID; // update the global var
  245. }
  246.  
  247.  
  248.  
  249.  
  250. void main()
  251. {
  252.    aiEcho("Starting Scn33p6.xs");
  253.  
  254.    //Calculate some areas.
  255.    kbAreaCalculate(1200.0);
  256.    aiRandSetSeed();
  257.    kbSetTownLocation(kbGetBlockPosition(cbTownCenter));
  258.  
  259. /*
  260.    aiSetAgeEventHandler(cAge2, "age2EventHandler");
  261.    aiSetAgeEventHandler(cAge3, "age3EventHandler");
  262.    aiSetAgeEventHandler(cAge4, "age4EventHandler");
  263. */
  264.    aiSetAttackResponseDistance(20.0);
  265.  
  266.    // Kill escrows
  267.    kbEscrowSetPercentage( cEconomyEscrowID, cAllResources, 0.0);
  268.    kbEscrowSetPercentage( cMilitaryEscrowID, cAllResources, 0.0);
  269.    kbEscrowAllocateCurrentResources();
  270.  
  271.  
  272.    int   armyReserveSize = -1;   // Target size for total reserve army, to be adjusted for difficulty
  273.    int   standardDelay = -1;     // Used to set unit-training delay times, adjusted for difficulty
  274.  
  275.    // Set difficulty vars
  276.    difficulty = aiGetWorldDifficulty();
  277.    aiEcho("Difficulty = "+difficulty);   
  278.  
  279.    switch(difficulty)      // Set up the attack control and age-up parameters
  280.    {
  281.    case 0:     // Easy
  282.       {
  283.          nextAttackTime = 1000;     // 1 sec
  284.          attackInterval = 240000;   // 4 min
  285.          attackSize = 4;          
  286.          attackMultiplier = 1.3;    // 30% per interval
  287.          maxAttackSize = 10;
  288.          age2Time = -1;       // N/A
  289.          age3Time = 1200000;  // 20 min
  290.          age4Time = 40*60*1000;       
  291.          armyReserveSize = 12;
  292.          standardDelay = 1;  // seconds
  293.          break;
  294.       }
  295.    case 1:     // Moderate
  296.       {
  297.          nextAttackTime = 1000;   // 1 sec 
  298.          attackInterval = 162000;   // 162 sec 
  299.          attackSize = 5.0;          
  300.          attackMultiplier = 1.3;    // 20% per period
  301.          maxAttackSize = 13;
  302.          age2Time = -1;       // N/A
  303.          age3Time = 720000;   // 12 min
  304.          age4Time = 20*60*1000;      
  305.          armyReserveSize = 16;
  306.          standardDelay = 1;  // seconds
  307.          break;
  308.       }
  309.    case 2:     // Difficult
  310.       {
  311.          nextAttackTime = 1000;     
  312.          attackInterval = 120000;
  313.          attackSize = 8.0;
  314.          attackMultiplier = 1.3;    // 30% per period
  315.          maxAttackSize = 20;
  316.          age2Time = -1;       // N/A
  317.          age3Time = 4*60*1000;   // 4 min
  318.          age4Time = 12*60*1000;       
  319.          armyReserveSize = 25;
  320.          standardDelay = 1;  // seconds
  321.          break;
  322.       }
  323.    case 3:     // Nightmare
  324.       {
  325.          nextAttackTime = 1000;
  326.          attackInterval = 120000;
  327.          attackSize = 11;
  328.          attackMultiplier = 1.4;    // 40% per period
  329.          maxAttackSize = 30;
  330.          age2Time = -1;       // N/A
  331.          age3Time = 1*60*1000;   // 1 min
  332.          age4Time = 8*60*1000;       
  333.          armyReserveSize = 40;
  334.          standardDelay = 1;  // seconds
  335.          break;
  336.       }
  337.    }
  338.  
  339.  
  340.  
  341.    // Set global unit control vars
  342.    maintainQty1 = (armyReserveSize+8)/10;         // Quantity to maintain
  343.    maintainUnit1 = cUnitTypeCyclops;        // Unit type
  344.    maintainDelay1 = standardDelay;       // Interval between training units
  345.    maintainGather1 = cInvalidVector;
  346.  
  347.    maintainQty2 = (4*armyReserveSize+2)/10;         // Quantity to maintain
  348.    maintainUnit2 = cUnitTypeHippikon;        // Unit type
  349.    maintainDelay2 = standardDelay;       // Interval between training units
  350.    maintainGather2 = cInvalidVector;
  351.  
  352.    maintainQty3 = (4*armyReserveSize+6)/10;         // Quantity to maintain
  353.    maintainUnit3 = cUnitTypeToxotes;        // Unit type
  354.    maintainDelay3 = standardDelay;       // Interval between training units
  355.    maintainGather3 = cInvalidVector;
  356.  
  357.    maintainQty4 = (armyReserveSize+5)/10;         // Quantity to maintain
  358.    maintainUnit4 = cUnitTypeHydra;        // Unit type
  359.    maintainDelay4 = standardDelay;       // Interval between training units
  360.    maintainGather4 = cInvalidVector;
  361.  
  362.  
  363.    maintainQtyScout = 1;
  364.    maintainUnitScout = cUnitTypePegasus;
  365.    maintainDelayScout = 1;
  366.    maintainGatherScout = cInvalidVector;
  367.  
  368.  
  369.    // Init attack routes
  370.    routeA = attackRoute("Attack Route A", cbRouteA1, cbRouteA2, cbRouteA3);
  371.    routeB = attackRoute("Attack Route B", cbRouteB1, cbRouteB2, cbRouteB3);
  372.    routeC = attackRoute("Attack Route C", cbRouteC1, cbRouteC2, cbRouteC3);
  373.  
  374.    // Init maintain plans
  375.    if (maintainUnit1 > 0)
  376.       maintainID1 = maintainUnit(maintainUnit1, maintainQty1, maintainGather1, maintainDelay1);
  377.    if (maintainUnit2 > 0)
  378.       maintainID2 = maintainUnit(maintainUnit2, maintainQty2, maintainGather2, maintainDelay2); 
  379.    if (maintainUnit3 > 0)
  380.       maintainID3 = maintainUnit(maintainUnit3, maintainQty3, maintainGather3, maintainDelay3);  
  381.    if (maintainUnit4 > 0)
  382.       maintainID4 = maintainUnit(maintainUnit4, maintainQty4, maintainGather4, maintainDelay4);  
  383.    if (maintainUnitScout > 0)
  384.       maintainIDScout = maintainUnit(maintainUnitScout, maintainQtyScout, maintainGatherScout, maintainDelayScout);
  385.  
  386.  
  387.  
  388.  
  389. /*
  390.    // Initialize the target queries
  391.    queryP1Units = kbUnitQueryCreate("Player 1 Units");
  392.    configQuery(queryP1Units, cUnitTypeUnit, -1, cUnitStateAlive, 1);
  393. */
  394.  
  395.  
  396. }
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404. // *****************************************************************************
  405. //
  406. // RULES
  407. //
  408. // *****************************************************************************
  409. /*rule cheatScout   // Spawn a fenris wolf if none exist
  410.    active
  411.    minInterval 15
  412. {
  413.    int count = -1;
  414.    count = kbUnitCount(2, maintainUnitScout, cUnitStateAlive);
  415.    if (count < maintainQtyScout)
  416.       aiUnitCreateCheat( 2, maintainUnitScout, kbGetBlockPosition(cbAttackGather), "Scout group", maintainQtyScout - count); 
  417.  
  418. }*/
  419.  
  420.  
  421.  
  422. rule favorGenerator
  423.    active
  424.    minInterval 15
  425. {
  426.    aiResourceCheat( 2, cResourceFavor, 100.0 );    // Max out the favor every 15 seconds
  427.    kbEscrowAllocateCurrentResources();             // Make sure the escrow knows about it.
  428. }
  429.  
  430.  
  431. rule scout
  432.    inactive
  433.    minInterval 5
  434. {
  435.    // just set up an explore plan
  436.    explorePlan = aiPlanCreate("Explore", cPlanExplore);
  437.    if(explorePlan >= 0)
  438.    {
  439.       aiPlanSetVariableFloat( explorePlan, cExplorePlanLOSMultiplier,  0, 4.0 );
  440.       aiPlanAddUnitType(explorePlan, maintainUnitScout, 1, 1, 1);
  441.       aiPlanSetDesiredPriority(explorePlan, 90);
  442.       aiPlanSetInitialPosition(explorePlan, kbGetBlockPosition(cbAttackGather));
  443.       aiPlanSetActive(explorePlan);
  444.    }
  445.    xsDisableSelf();
  446. }
  447.  
  448.  
  449.  
  450. /*
  451. rule goToAge2
  452.    inactive
  453.    minInterval 10
  454. {
  455.    if ( xsGetTime() < age2Time)
  456.       return;
  457.    researchTech(cTechAge2Heimdall);
  458.    xsDisableSelf();
  459. }
  460.  
  461.  
  462.  
  463. rule goToAge3
  464.    inactive
  465.    mininterval 20
  466. {
  467.    if ( xsGetTime() < age3Time )
  468.       return;
  469.    researchTech(cTechAge3Njord);
  470.    xsDisableSelf();
  471. }
  472.  
  473.  
  474. rule goToAge4
  475.    inactive
  476.    mininterval 20
  477. {
  478.    if ( xsGetTime() < age4Time )
  479.       return;
  480.    researchTech(cTechAge4Hel);
  481.    xsDisableSelf();
  482. }
  483. */
  484.  
  485.  
  486.  
  487. rule getAge2UnitUpgrades
  488.    inactive
  489.    minInterval 20
  490. {
  491. //   researchTech(cTechMediumInfantry);
  492. //   researchTech(cTechMediumCavalry);
  493.    xsDisableSelf();
  494. }
  495.  
  496. rule getAge2ArmoryUpgrades
  497.    inactive
  498.    minInterval 20
  499. {
  500.  
  501.    aiEcho("Getting age 2 armory upgrades");
  502.    researchTech(cTechCopperWeapons);
  503.    researchTech(cTechCopperMail);
  504.    researchTech(cTechCopperShields);
  505.    xsDisableSelf();
  506. }
  507.  
  508. rule getAge3UnitUpgrades
  509.    inactive
  510.    minInterval 20
  511. {
  512.  
  513. //   researchTech(cTechHeavyInfantry);
  514.  //  researchTech(cTechHeavyCavalry);
  515.    xsDisableSelf();
  516. }
  517.  
  518. rule getAge3ArmoryUpgrades
  519.    inactive
  520.    minInterval 20
  521. {
  522.    aiEcho("Getting age 3 armory upgrades");
  523.    researchTech(cTechBronzeWeapons);
  524.    researchTech(cTechBronzeMail);
  525.    researchTech(cTechBronzeShields);
  526.    xsDisableSelf();
  527. }
  528.  
  529. rule getAge4UnitUpgrades
  530.    inactive
  531.    minInterval 20
  532. {
  533.  
  534. //   researchTech(cTechChampionInfantry);
  535. //   researchTech(cTechChampionCavalry);
  536.    xsDisableSelf();
  537. }
  538.  
  539. rule getAge4ArmoryUpgrades
  540.    inactive
  541.    minInterval 20
  542. {
  543.    aiEcho("Getting age 4 armory upgrades");
  544.    researchTech(cTechIronWeapons);
  545.    researchTech(cTechIronMail);
  546.    researchTech(cTechIronShields);
  547.    xsDisableSelf();
  548. }
  549.  
  550.  
  551. rule upgradeGenerator
  552.    minInterval 10
  553.    inactive
  554. {
  555.    // Progressively get unit upgrades throughout
  556.    // Take the time from startTime to endTime, divide into six segments.
  557.    // At the end of each segment, get a set of unit or armory upgrades.
  558.  
  559.    static int interval = 0;
  560.    static int nextTime = 0;
  561.    static int count = 0;
  562.  
  563.    if (interval == 0) 
  564.    {
  565.       interval = (endTime - startTime)/6;
  566.       nextTime = startTime + interval;
  567.    }
  568.  
  569.    if (nextTime > xsGetTime())
  570.       return;     // It is not yet our time.
  571.  
  572.    // It is time, do something
  573.    switch( count )      // Activate the appropriate upgrade rule, reset nextTime timer.
  574.    {
  575.    case 0:
  576.       {
  577.          xsEnableRule("getAge2UnitUpgrades");
  578.          count = count + 1;
  579.          nextTime = nextTime + interval;
  580.          break;
  581.       }
  582.    case 1:
  583.       {
  584.          xsEnableRule("getAge2ArmoryUpgrades");
  585.          count = count + 1;
  586.          nextTime = nextTime + interval;
  587.          break;
  588.       }
  589.    case 2:
  590.       {
  591.          xsEnableRule("getAge3UnitUpgrades");
  592.          count = count + 1;
  593.          nextTime = nextTime + interval;
  594.          break;
  595.       }
  596.    case 3:
  597.       {
  598.          xsEnableRule("getAge3ArmoryUpgrades");
  599.          count = count + 1;
  600.          nextTime = nextTime + interval;
  601.          break;
  602.       }
  603.    case 4:
  604.       {
  605.          xsEnableRule("getAge4UnitUpgrades");
  606.          count = count + 1;
  607.          nextTime = nextTime + interval;
  608.          break;
  609.       }
  610.    case 5:
  611.       {
  612.          xsEnableRule("getAge4ArmoryUpgrades");
  613.          count = count + 1;
  614.          xsDisableSelf();
  615.          break;
  616.       }
  617.    }
  618.  
  619.  
  620. }
  621.  
  622. rule attackGenerator
  623.    minInterval 10
  624.    inactive
  625. {
  626.    //aiEcho("attack check running, next time is "+nextAttackTime);
  627.    if ( xsGetTime() < nextAttackTime )
  628.       return;
  629.  
  630.    attack(attackSize);
  631.    nextAttackTime = xsGetTime() + attackInterval;
  632.    attackSize = attackSize * attackMultiplier;
  633.    if (attackSize > maxAttackSize)
  634.       attackSize = maxAttackSize;
  635.    aiEcho("Next attack size will be "+attackSize+".");
  636. }
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643. rule usePestilence // Look for 3 military production buildngs near the pegasus scout
  644.    minInterval 5
  645.    inactive
  646. {
  647.    int targetUnit = -1;
  648.    int attackArmyID = -1;
  649.  
  650.    if (xsGetTime() < (startTime + 2*60*1000))
  651.       return;
  652.  
  653.    if (explorePlan < 0)
  654.       return;
  655.    vector pVec = aiPlanGetLocation(explorePlan);
  656.    if (xsVectorGetX(pVec)<0)
  657.       return;
  658.  
  659.    static int tempQuery = -1;
  660.    if (tempQuery < 0)
  661.    {  // Doesn't exist, set it up
  662.       tempQuery = kbUnitQueryCreate("usePestilence");
  663.  
  664.       if ( configQuery(tempQuery, cUnitTypeLogicalTypeBuildingsThatTrainMilitary, -1, cUnitStateAliveOrBuilding, 1, pVec, true, 30) == false)
  665.          return;
  666.    }
  667.    else
  668.       kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
  669.  
  670.    kbUnitQueryResetResults(tempQuery);
  671.    int targetCount = kbUnitQueryExecute(tempQuery);  
  672.  
  673.    if (targetCount < 3)
  674.       return;
  675.    targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2);  // grab middle building
  676.  
  677.    // confirm LOS
  678.    if ( kbUnitVisible(targetUnit) != true )
  679.    {
  680.       aiEcho("Pestilence: Don't have LOS for unit "+targetUnit+" "+kbGetProtoUnitName(targetUnit));
  681.       return;
  682.    }
  683.  
  684.    aiEcho("Using Pestilence at "+kbUnitGetPosition(targetUnit));
  685.    if ( aiCastGodPowerAtPosition(cTechPestilence, kbUnitGetPosition(targetUnit)) == true)
  686.       xsDisableSelf();
  687.    else 
  688.       aiEcho("Pestilence failed at "+kbUnitGetPosition(targetUnit));
  689. }
  690.  
  691.  
  692.